from queue import Queue
from ParseGesture import data2allowCode, data2userCode, bit_allowed_all
from DoAction import doAction

store={}#for action  [last_tran_act,last_action]
multi_hand_last_tran_act_l=[]
multi_hand_fsm_l=[]

# 更新自动机列表
def updateFSMS(multi_hand_fsms):
    global multi_hand_fsm_l, multi_hand_last_tran_act_l
    multi_hand_fsm_l=multi_hand_fsms
    multi_hand_last_tran_act_l=[
            [
                [None,None] for x in range(len(fsm_l))
            ] for fsm_l in multi_hand_fsm_l
        ]

# 判断状态转移条件是否满足
def isAllow(pose,unclear,trans_mask):
    pose_clear=pose|unclear#集合编码1011=1000|0011
    allowed = pose_clear&trans_mask#=1011&1011,1010,0010
    if allowed==pose_clear:#允许
        return 1
    elif (allowed^pose_clear)&(~unclear):#1010&1100=1000,存在非不确定位范围内的不相同位，不允许
        return 0
    else:#不确定
        return -1

def testIsAllow():
    right=[]
    for i in range(8):
        trans_mask=(i&4)>>2
        unclear=(i&2)>>1
        pose=i&1
        ret = isAllow(pose,unclear,trans_mask)
        res="{:>1b} {:>b} {:>1b} {}\n".format(pose,unclear,trans_mask, ret)
        print(res)
        right.append(res)
    for i in range(64):
        trans_mask=(i&48)>>4
        unclear=(i&12)>>2
        pose=i&3
        ret = isAllow(pose,unclear,trans_mask)
        res="{:0>2b} {:0>2b} {:0>2b} {}\n".format(pose,unclear,trans_mask, ret)
        print(res)
        right.append(res)
    with open("testIsAllow.txt","w") as f:
        f.writelines(right)


# 判断是否是上一个同样动作
def isLast(pose,unclear,last_tran_act): 
    state=0#默认没有last_tran_act从0state开始
    if last_tran_act[0]:
        # 判断上个动作是否结束
        res_allow=isAllow(pose,unclear,last_tran_act[0][0])
        if last_tran_act[0][0]==bit_allowed_all or res_allow==0:
            # 若条件"*"或不满足则结束上个转移
            state=last_tran_act[0][1]
            last_tran_act[1]=None
            return False, state, None
        elif res_allow==1:
            # 满足，继续执行上个动作
            return True, state, last_tran_act[1]        
        elif res_allow==-1:
            # 可能满足，继续判断
            return True, state, None
    # 不存在上个转移，是第一个状态
    return False, state, None

# 测试判断是否是上一个同样姿态
def testIsLast():
    right=[]
    last_tran_act_l=[   
                        [0,1],
                        [bit_allowed_all,1]
                    ]
    last_tran_act0=[None,None]
    last_tran_act=last_tran_act0.copy()
    ret = isLast(0,0,last_tran_act)
    res="{:>1b} {:>1b} {:<35} {:<35} {}\n".format(0,0,str(last_tran_act0),str(last_tran_act),ret)
    right.append(res)
    for last_tran_act0 in last_tran_act_l:
        last_tran_act0=[last_tran_act0,None]
        for pose, unclear in [(0,0),(1,0),(0,1)]:
            last_tran_act0[1]=None
            last_tran_act=last_tran_act0.copy()
            last_tran_act[0]=last_tran_act[0].copy()
            ret = isLast(pose,unclear,last_tran_act)
            res="{:>1b} {:>1b} {:<35} {:<35} {}\n".format(pose,unclear,str(last_tran_act0),str(last_tran_act),ret)
            right.append(res)

            last_tran_act0[1]="## Action"
            last_tran_act=last_tran_act0.copy()
            last_tran_act[0]=last_tran_act[0].copy()
            ret = isLast(pose,unclear,last_tran_act)
            res="{:>1b} {:>1b} {:<35} {:<35} {}\n".format(pose,unclear,str(last_tran_act0),str(last_tran_act),ret)
            right.append(res)
    with open("testIsLast.txt","w") as f:
        f.writelines(right)

# 判断当前状态是否有满足条件转移
def isNext(fsm, state, data, pose, unclear, last_tran_act):
    has_possible_trans=False
    for trans in fsm[state]:
        if (not trans) or type(trans) is str:
            # 无选择或为Action
            continue
        res_allow=isAllow(pose,unclear,trans[0])
        if res_allow==-1:#有可能满足条件
            has_possible_trans=True
            continue
        elif res_allow==0:#不允许转移
            continue
        else:#允许转移
            # 更新上次转移
            action = (fsm[trans[1]])[0]
            if action and len(action)>2 and action[2]=='+':
                last_tran_act[1]=action
            else:
                last_tran_act[1]=None
            last_tran_act[0]=trans
            # 执行动作
            doAction(action, data, store)
            break
    else:
        if not has_possible_trans:
            # 无任何可能满足任一条件
            last_tran_act[0]=None

# 测试判断当前状态是否有满足条件转移
def testIsNext():
    fsms=[
        {0:[None,[0,1]],1:["## Action0"]},
        {0:[None,[1,1]],1:["## Action0"]},
        {0:[None,[0,1]],1:["##+Action1"]},
        {0:[None,[1,1]],1:["##+Action1"]}
    ]
    right=[]
    for pose, unclear in [(0,0),(1,0),(0,1)]:
        for fsm in fsms:
            last_tran_act=[[-1,-1],"#"]
            isNext(fsm, 0, None, pose, unclear, last_tran_act)
            res="{:>1b} {:>1b} {:<50} {:<50}\n".format(pose,unclear,str(fsm),str(last_tran_act))
            right.append(res)
    with open("testIsNext.txt","w") as f:
        f.writelines(right)

def matchGesture (poses_in_queue, END_SIG):
    updateFSMS(multi_hand_fsm_l)
    while True:
        multi_hand_data = poses_in_queue.get()
        if multi_hand_data is END_SIG:
            poses_in_queue.put(END_SIG)
            break
        num_hands_data=len(multi_hand_data)
        pose_unclear_l=data2allowCode(multi_hand_data)
        for i_hand,last_tran_act_l in enumerate(multi_hand_last_tran_act_l):
            
            # 遍历未识别到的手，清空转移状态
            if i_hand>=num_hands_data:
                for last_tran_act in last_tran_act_l:
                    last_tran_act[0]=None
                continue
            
            fsm_l = multi_hand_fsm_l[i_hand]
            data = multi_hand_data[i_hand]                      
            pose, unclear=pose_unclear_l[i_hand]
            for fsm, last_tran_act in zip(fsm_l,last_tran_act_l):
                res, state, action=isLast(pose,unclear,last_tran_act)
                if res:# 上个转移进行中
                    doAction(action,data,store)
                    continue
                # 尝试下个转移
                isNext(fsm, state, data, pose, unclear, last_tran_act)

if __name__ == '__main__':
    # testIsAllow()
    testIsLast()
    # testIsNext()